home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-04
/
ddj1291.zip
/
STAT.ZIP
/
SOURCE.ZIP
/
PAUTIL.C
< prev
next >
Wrap
C/C++ Source or Header
|
1990-05-09
|
14KB
|
474 lines
/*
** File: pautil.c
**
** Copyright 1990
** Fred Motteler and Applied Microsystems Corporation
** All Rights Reserved
**
** Description: Utility functions used by the statistical performance
** analysis package.
*/
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include "padef.h"
/* Debugging level flag, pick one */
int pa_debugN = PA_NO_DEBUG;
/* int pa_debugN = PA_SER_IN; */
/*
** Function: int pa_hextobin( int charN )
**
** Description: This function converts the ASCII hexidecimal character charN
** to a binary value 0 to 15. If the input character is not
** a valid hexidecimal digit, then a -1 is returned.
*/
int
pa_hextobin( charN )
int charN; /* Character to convert */
{
if( (charN >= (int)'0') && (charN <= (int)'9')) return( charN - (int)'0' );
if( (charN >= (int)'A') && (charN <= (int)'F')) return( charN - (int)'7' );
if( (charN >= (int)'a') && (charN <= (int)'f')) return( charN - (int)'W' );
return( -1 ); /* Not a hex character */
}
/*
** Function: int pa_hitcomp(struct padata *a, struct padata *b)
**
** Description: This function is compares the magnitude of a->hitsL and
** b->hitsL. It is used by the ANSI qsort() function to
** sort the pointers in patableAHP according to the number
** of program counter "hits" within each function. It returns
** 1, 0, or -1 depending on the relative magnitude of a->hitsL and b->hitsL.
*/
int
pa_hitcomp(a, b)
struct padata **a;
struct padata **b;
{
if (((*b)->hitsL) > ((*a)->hitsL)) return(1);
if (((*b)->hitsL) < ((*a)->hitsL)) return(-1);
return(0);
}
/*
** Function: int pa_addrcomp(struct padata *a, struct padata *b)
**
** Description: This function is compares the magnitude of a->addressL and
** b->addressL. It is used by the ANSI qsort() functions to
** sort the pointers in patableAHP. It returns 1, 0, or -1
** depending on the relative magnitude of a->addressL and
** b->addressL.
*/
int
pa_addrcomp(a, b)
struct padata **a;
struct padata **b;
{
if (((*b)->addressL) > ((*a)->addressL)) return(-1);
if (((*b)->addressL) < ((*a)->addressL)) return(1);
return(0);
}
/*
** Function: char *pa_strsrch( stringBP, searchBP )
**
** Description: Search for the first occurance of string "searchBP" in
** "stringBP". If found, then return a pointer to the first
** occurance of searchBP in stringBP. If not found, then
** return a NULL pointer.
*/
char *
pa_strsrch( stringBP, searchBP )
char *stringBP; /* String to search */
char *searchBP; /* String being searched for */
{
int len_strN; /* Length of string to search */
int len_srchN; /* Length of string being searched for */
int searchN;
len_strN = strlen(stringBP);
len_srchN = strlen(searchBP);
searchN = len_srchN;
/* Search for the string only if the string to be searched is longer than
* or equal in length to the string being searched for. */
if (len_strN >= len_srchN)
{
/* Search only if the remaining portion of the string to be searched
* is longer than or equal in length to the string being searched
* for. */
while( len_strN >= len_srchN++ ) {
if (strncmp( searchBP, stringBP, searchN) == 0)
return( stringBP );
stringBP++;
}
}
return( (char *) NULL );
}
/*
** Function: int paconfig( FILE *formatFP, char *idstrPC, char *fieldstrPC )
**
** Description: The function searches the configuration file for the
** field specified in the string pointed to by idstrPC. The
** string value in the field is returned in the buffer pointed
** to by fieldstrPC.
**
** For example, in the line:
**
** START_ID:"Symbols by value"
**
** START_ID is the field identifier, and "Symbols by value" is
** the field value. The double quotes are required to delimit
** the field value and are removed when the value string is
** returned to the calling program. A field value string of
** "" is legal and results in a empty string being returned.
**
** This function returns 0 if the operation is successful,
** otherwise and error code is return.
*/
int
paconfig(formatFP, idstrPC, fieldstrPC)
FILE *formatFP; /* Configuration file */
char *idstrPC; /* String giving field to find */
char *fieldstrPC; /* Pointer to found field */
{
char lineAB[PA_LINE_LEN]; /* Local buf for line read from config file */
char *tempPC; /* Working pointer */
/* Seek to the start of the file */
if (fseek(formatFP, 0, 0) == (-1))
return(PA_CFG_SEEK_E);
/* Search for the field identifier */
while (fgets(lineAB, PA_LINE_LEN, formatFP) != (char *) NULL)
{
/* Search the line for the string that preceeds the
* string used to start reading in the data. */
if ((tempPC = strstr(lineAB, idstrPC)) != (char *) NULL)
{
/* Found the field, check the rest of the line for the entry.
** The first and last characters should be a double quotes. */
tempPC += strlen(idstrPC);
if (*tempPC == '\0')
return(PA_FIELD_E);
else if (*tempPC != 0x22)
return(PA_BAD_DEL_E);
/* Copy the entry to the result buffer. */
tempPC++; /* Skip initial double quote */
strcpy(fieldstrPC, tempPC);
/* Search for double quote terminator, and replace it with a
* a nul terminator. */
while (*fieldstrPC != 0x22)
{
if (*fieldstrPC == '\0')
return(PA_BAD_DEL_E);
else
fieldstrPC++;
}
*fieldstrPC = '\0'; /* Replace it with a nul terminator */
return(0);
}
}
/* Entry not found, return an error code. */
return(PA_CFG_FIELD_E);
}
/*
** Function: int pa_zero_hits(struct padata **bintabP, int processedN)
**
** Description: This function does a "pre-pass" of the sample bin table,
** "throwing out" all function entries that have zero program
** counter hits associated with them.
**
** This is done by a simple swap of zero hit entries for non-zero
** entries.
**
** The number of entries with non-zero hits counts is returned.
**
** Use of the construct bintabP[i] is used instead of *(bintabP+i)
** for the sake of readibility.
*/
int
pa_zero_hits(bintabP, processedN)
struct padata **bintabP; /* Pointer to a table of pointers to padata
* data structures, these structures actually
* contain the function name, address, and
* number of program counter hits. */
int processedN; /* Number of entries in the pointer table. */
{
int i,j;
struct padata *tempHP; /* Temporary pointer for pre-sort */
if ((pa_debugN & PA_GENERAL) != 0)
printf("pa_zero_hits: removing zero hits\n");
/* Loop through the sample table, searching for entries with zero hits. */
for (i = 0; i < (processedN - 1); i++)
{
/* Check if the current hitsL count is zero */
if ((bintabP[i]->hitsL) == 0L)
{
/* The current hitsL count is zero, search for the first non-zero
* hitL value and swap the two... */
for( j = i + 1; j < processedN; j++)
{
if ((bintabP[j]->hitsL) != 0L)
{
tempHP = bintabP[j];
bintabP[j] = bintabP[i];
bintabP[i] = tempHP;
break;
}
}
/* Check if all remaining elements are zero, if so, then quit. */
if (j == processedN)
break;
}
}
/* The value of i gives the location of the first zero entry. */
if ((pa_debugN & PA_GENERAL) != 0)
printf("pa_zero_hits: %d bins with samples\n",i);
return(i);
}
/*
** Function: int pa_bstuff(char *sampfileS, struct padata **bintabP,
** int processedN)
**
** Description: This function reads the sample file whose name is given
** in the string sampfileS. The value of processedN gives
** the number of global symbol "bins" in the table pointed
** to by bintabP. bintabP is actually a pointer to a table
** pointers to padata structures that contain the symbol,
** address, and hit count information.
**
** Once the sample file has been processed, any "bins"
** with zero hits are effectively removed, and the resulting
** bins are sorted according to the number of hits in each
** bin.
**
** Zero is returned upon successful completion of reading
** the sample file in and incremented the appropriate
** sampling "bins" in the padata structures.
*/
int
pa_bstuff(sampfileS, bintabP, processedNP)
char *sampfileS; /* Sample file to process */
struct padata **bintabP; /* Pntr to table of pntrs to padata structs
* that contain function, address, and hit
* values. */
int *processedNP; /* Pntr to number of globals in padata table */
{
int handleN; /* Sample file handle */
unsigned long pcvalueL; /* Value of pc read from sample file */
int readsizeN; /* Number of bytes read from sample file */
int stepN; /* Current binary search step size */
int curbinN; /* Current index of element being compared */
int hitbinsN; /* Number of bins with hits */
int i; /* General index */
/* Read the samples from a binary file. */
if ((handleN = open (sampfileS, (O_RDONLY | O_RAW), 0)) == (-1))
return(PA_NO_PC_FILE_E);
while ((readsizeN = read( handleN, ((char *) &pcvalueL), 4)) == 4)
{
if ((pa_debugN & PA_GENERAL) != 0)
printf("pa_bstuff: sample value: %lx\n", pcvalueL);
/* Do a binary search for the proper bin to increment. */
stepN = *processedNP >> 1;
curbinN = stepN; /* Start in the middle */
/* Loop until we find the right bin */
while (((bintabP[curbinN]->addressL) > pcvalueL) ||
((bintabP[curbinN+1]->addressL) <= pcvalueL))
{
/* Half the step size. */
if (stepN > 1)
stepN >>= 1;
if (stepN == 0)
return(PA_BSTEP_ZERO_E);
/* Check if pc value is less than current bin lower bound. */
if ((bintabP[curbinN]->addressL) > pcvalueL)
{
curbinN -= stepN;
if (curbinN < 0)
curbinN = 0;
}
/* Check if pc value is greater than current bin upper bound. */
else if ((bintabP[curbinN+1]->addressL) <= pcvalueL)
{
curbinN += stepN;
if (curbinN >= *processedNP)
curbinN = *processedNP - 1;
}
}
/* Increment the appropriate bin. */
(bintabP[curbinN]->hitsL)++;
}
/* Done reading in the pc sample file. */
close( handleN );
if (remove(sampfileS) != 0)
return(PA_NO_PC_DEL_E);
/* Check for any problems reading in the sample file. */
if (readsizeN == EOF)
return(PA_NO_PC_RD_E);
if ((pa_debugN & PA_GENERAL) != 0)
{
printf("%d global symbols\n",*processedNP);
printf("Dump of table sorted by address, with sample counts\n");
for (i = 0; i < *processedNP; i++)
{
printf("%s %lx %ld\n",
((bintabP[i])->symbolAB),
((bintabP[i])->addressL),
((bintabP[i])->hitsL));
}
}
/* Throw out any sample bins that did not get any pc hits. */
if((hitbinsN = pa_zero_hits(bintabP, *processedNP)) == 0)
return(PA_NO_HIT_BINS_E);
/* The map file has been read in, now sort it according to value. */
qsort(bintabP, hitbinsN, sizeof(struct padata *), pa_hitcomp);
return(0);
}
/*
** Function: void pa_error(int errorN)
**
** Description: This function prints out an error message that corresponds
** to the given error message.
*/
void
pa_error(errorN)
int errorN; /* Error code of message to print. */
{
switch(errorN)
{
case PA_BAD_HEX_E:
printf("Hex digit expected\n");
break;
case PA_NO_SYMBOL_E:
printf("Address value with no symbol\n");
break;
case PA_EARLY_END_E:
printf("File ended unexpectedly\n");
break;
case PA_TAB_FULL_E:
printf("Map table is full\n");
break;
case PA_NO_MEM_E:
printf("Out of memory\n");
break;
case PA_NO_WHERE_E:
printf("Can't exec pawhere.exe\n");
break;
case PA_NO_TMP_E:
printf("Can't find pawhere.tmp\n");
break;
case PA_BAD_TMP_E:
printf("Can't properly read pawhere.tmp\n");
break;
case PA_TMP_RM_E:
printf("Can't remove pawhere.tmp\n");
break;
case PA_ES_NORESP_E:
printf("ES 1800 not responding\n");
break;
case PA_NO_TUP_FILE_E:
printf("Can't open file for TUP response\n");
break;
case PA_NO_TUP_WR_E:
printf("Can't write to TUP response file\n");
break;
case PA_NOT_IMPL_E:
printf("Function not implemented\n");
break;
case PA_NO_EXEC_E:
printf("Can't exec test program\n");
break;
case PA_NO_PC_FILE_E:
printf("Can't open file for pc samples\n");
break;
case PA_NO_PC_WR_E:
printf("Can't write to pc sample file\n");
break;
case PA_CFG_SEEK_E:
printf("Can't seek to start of cfg file\n");
break;
case PA_CFG_FIELD_E:
printf("Can't find field in cfg file\n");
break;
case PA_FIELD_E:
printf("Field in cfg file is empty\n");
break;
case PA_BAD_DEL_E:
printf("Field has bad or no delimiter\n");
break;
case PA_BAD_ORDER_E:
printf("Bad symbol value order field\n");
break;
case PA_MAP_FMT_E:
printf("Bad map format specification\n");
break;
case PA_BSTEP_ZERO_E:
printf("Binary search step is zero\n");
break;
case PA_NO_PC_DEL_E:
printf("Can't remove pc sample file\n");
break;
case PA_NO_PC_RD_E:
printf("Can't read from pc sample file\n");
break;
case PA_NO_MAP_E:
printf("Can't open map file\n");
break;
case PA_NO_CFG_E:
printf("Can't open the configuration file\n");
break;
case PA_NO_HIT_BINS_E:
printf("No bins accumulated any hits\n");
break;
case PA_BAD_ARG_E:
printf("Bad argument passed\n");
break;
case PA_NO_LST_E:
printf("Can't open results listing file\n");
break;
case PA_NO_DRT_FILE_E:
printf("Can't open file for DRT response\n");
break;
case PA_NO_DRT_WR_E:
printf("Can't write to DRT response file\n");
break;
case PA_BAD_DRT_RD_E:
printf("Can't properly read DRT data\n");
break;
case PA_DCOUNT_OUT_E:
printf("DRT digit count is out of bounds\n");
break;
case PA_LCOUNT_OUT_E:
printf("DRT line count is out of bounds\n");
break;
default:
printf("Unrecognized error code %d\n",errorN);
break;
}
return;
}